package alarm_monitor

import (
	"context"
	"device-admin/config/redis"
	"device-admin/internal/define"
	"strconv"
	"strings"
	"time"

	"192.168.1.75/go-pkg/logx"
	_redis "github.com/go-redis/redis/v8"
)

// 定义可合并的告警类型
// 当触发可合并的告警类型时，暂缓告警
type alarmMerge struct{}

// DelayAlarm 延迟告警
// robotID 机器id
func (alarmMerge) delayAlarm(robotID string, oldAlarmType, newAlarmType int, checkTime int64, mergeTimeout int64) bool {
	rdb := redis.NewDB()
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()
	newCheckTime := time.Now().Unix() + mergeTimeout
	alarmSetKeyOld := genAlarmSetKey(robotID, oldAlarmType, checkTime)
	alarmSetKeyNew := strings.Join([]string{robotID, strconv.Itoa(newAlarmType), strconv.Itoa(int(newCheckTime))}, "_")
	// 延迟告警并延期状态目标值
	{
		// 获取旧的alarmSetKey的值
		status0, err := rdb.Get(ctx, define.RedisAlarmMonitorStatus+alarmSetKeyOld).Int()
		if err != nil {
			logx.Error(context.Background(), "DelayAlarm:get old dst status failed")
			return false
		}
		// 添加新的监控对象
		rdb.ZAdd(ctx, define.RedisAlarmMonitorSet, &_redis.Z{
			Score:  float64(newCheckTime), // 计算时间的分值
			Member: alarmSetKeyNew,
		}).Result()
		// 设置新的目标状态监控值
		rdb.Set(ctx, define.RedisAlarmMonitorStatus+alarmSetKeyNew, status0, time.Second*time.Duration(mergeTimeout+30))
	}
	// 如果存在告警合并配置，且还未进行合并处理
	mergeType := define.AlarmType[newAlarmType].MergeType
	mergeTypeKey := strings.Join([]string{robotID, strconv.Itoa(mergeType)}, "_")
	// 合并标记
	// 获取延迟标志中已经合并的告警，并合并新的告警
	// key组合采用合并告警类型
	{
		// 计算合并告警
		mergedVal := strings.Join([]string{strconv.Itoa(newAlarmType), strconv.Itoa(int(newCheckTime))}, "_")
		mergedAlarm, _ := rdb.Get(ctx, define.RedisAlarmMonitorMerge+mergeTypeKey).Result()
		if mergedAlarm != "" && !strings.Contains(mergedAlarm, strconv.Itoa(newAlarmType)+"_") {
			mergedAlarm = mergedAlarm + "," + mergedVal
		} else {
			mergedAlarm = mergedVal
		}
		// 更新已经合并的告警
		rdb.Set(
			ctx,
			define.RedisAlarmMonitorMerge+mergeTypeKey,
			mergedAlarm,
			time.Second*time.Duration(mergeTimeout+30),
		)
		return true
	}
}

// MergeConfirm 合并确认
func (alarmMerge) mergeConfirm(robotID string, alarmMergeType int) {
	rdb := redis.NewDB()
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()
	mergeTypeKey := strings.Join([]string{robotID, strconv.Itoa(alarmMergeType)}, "_")
	mergedAlarms, _ := rdb.Get(ctx, define.RedisAlarmMonitorMerge+mergeTypeKey).Result()
	mergedAlarmArr := strings.Split(mergedAlarms, ",")
	// 合并完成
	if len(mergedAlarmArr) >= alarmMergeGroupCount[alarmMergeType] {
		// 推送合并告警
		AlarmMonitor{}.PushAlarm(robotID, alarmMergeType)
		// 删除子告警
		for _, mergedAlarm := range mergedAlarmArr {
			arr := strings.Split(mergedAlarm, "_")
			alarmType := arr[0]
			checkTime := arr[1]
			if len(arr) == 2 {
				rdb.ZRem(ctx, define.RedisAlarmMonitorSet, robotID+"_"+alarmType+"_"+checkTime).Result()
			}
		}
		// 删除结果合并缓存
		rdb.Del(ctx, define.RedisAlarmMonitorMerge+mergeTypeKey)
	}
}

// HasMerged 是否合并过
func (alarmMerge) HasMerged(robotID string, alarmType int) bool {
	rdb := redis.NewDB()
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
	defer cancel()

	mergeType := define.AlarmType[alarmType].MergeType
	mergeTypeKey := strings.Join([]string{robotID, strconv.Itoa(mergeType)}, "_")
	mergedAlarms, _ := rdb.Get(ctx, define.RedisAlarmMonitorMerge+mergeTypeKey).Result()
	return strings.Contains(mergedAlarms, strconv.Itoa(alarmType)+"_")
}
